<?php
namespace app\http\controller;

use think\Db;
use think\facade\Cache;
use think\session\driver\Redis;
use think\worker\Server;
use Workerman\Connection\TcpConnection;
use Workerman\Lib\Timer;

class Worker extends Server
{
    protected $connections = [];

    public function onConnect(TcpConnection $connection)
    {
        $this->connections[$connection->id] = $connection;
        $connection->lastMessageTime = time();
    }

    public function onMessage($connection,$message)
    {
        $connection->lastMessageTime = time();
        $message_data = json_decode($message, true);
        if(!$message_data)
        {
            return ;
        }
        $client_id = $connection->id;
        $redis = new \Redis();
        $redis->connect('127.0.0.1', 6379);
        $room_key = 'live_'.$message_data['room_id'];
        $user_key = 'live_'.$message_data['room_id'].'_'.$message_data['user_id'];
//        $connection->send(json_encode([123]));
        // 根据类型执行不同的业务
        switch($message_data['type'])
        {
            // 客户端回应服务端的心跳
            case 'ping':
                $liveInfo = Db::name('live')->where(['id' => $message_data['room_id']])->find();
                if($liveInfo['live_status']){
                    $liveUser = Db::name('live_user')->where(['live_id' => $message_data['room_id'],'user_id' => $message_data['user_id']])->find();
                    if($liveUser && $liveUser['upd_time'] > 0){
                        Db::name('live_user')->where(['live_id' => $message_data['room_id'],'user_id' => $message_data['user_id']])->update([
                            'second' => $liveUser['second'] + (time() - $liveUser['upd_time']),
                            'upd_time' => time(),
                        ]);
                    }
//                    if($liveInfo['task_ids']){
//                        $mins = floor($liveUser['second']/60);
//                        $task = Db::name('live_task')->where('id','in',$liveInfo['task_ids'])->where('condition','<',$mins)->find();
//                        $count = Db::name('live_task_log')->where(['pid' => $task['id'],'user_id' => $message_data['user_id']])->find();
//                        if($task && !$count){
//                            $send_data = [
//                                'type' => 'task',
//                                'task_id' => $task['id'],
//                                'room_id' => $message_data['room_id'],
//                                'name' => $message_data['name'],
//                                'user_id' => $message_data['user_id']
//                            ];
//                            $connection->send(json_encode($send_data));
//                        }
//                    }
                }
                return;
            // 客户端登录 message格式: {type:login, name:xx, room_id:1} ，添加到客户端，广播给所有客户端xx进入聊天室
            case 'login':
                $nickname = Db::name('users')->where('user_id',$message_data['user_id'])->value('nick_name');
                if(!$nickname){
                    $nickname = '用户'.$message_data['user_id'];
                }
                // 判断是否有房间号
                if(!isset($message_data['room_id']))
                {
                    throw new \Exception("\$message_data['room_id'] not set. client_ip:{$_SERVER['REMOTE_ADDR']} \$message:$message");
                }
                $count = Db::name('live_user')->where(['live_id' => $message_data['room_id'],'user_id' => $message_data['user_id']])->count();
                $liveInfo = Db::name('live')->where(['id' => $message_data['room_id']])->find();
                if($liveInfo['live_status']){
                    $upd_time = time();
                }else{
                    $upd_time = 0;
                }
                if($count){
                    Db::name('live_user')->where(['live_id' => $message_data['room_id'],'user_id' => $message_data['user_id']])->update([
                        'is_online' => 1,
                        'upd_time' => $upd_time
                    ]);
                }else{
                    Db::name('live_user')->insert([
                        'live_id' => $message_data['room_id'],
                        'user_id' => $message_data['user_id'],
                        'add_time' => time(),
                        'is_online' => 1,
                        'second' => 0,
                        'upd_time' => $upd_time
                    ]);
                }
//                $this->connections[$client_id] = $connection;
                $redis->setex('fd_'.$client_id,86400,$message_data['room_id']);
                $redis->setex('user_'.$client_id,86400,$message_data['user_id']);
                $redis->sadd($room_key,$client_id);
                $redis->setex($user_key,86400,json_encode([
                    'client_id' => $client_id,
                    'room_id' => $message_data['room_id'],
                    'name' => $nickname,
                    'user_id' => $message_data['user_id']
                ]));
                $real_num = $redis->scard($room_key);
                $online_num = $liveInfo['virtual_user'] + $real_num + rand($real_num,$real_num + 20);
                //给所有用户发送消息
                $user_list = $redis->smembers($room_key);
                foreach ($user_list as $fd){

                    $send_data = [
                        'type' => 'login',
                        'fd_id' => $fd,
                        'room_id' => $message_data['room_id'],
                        'name' => $nickname,
                        'user_id' => $message_data['user_id'],
                        'online_num' => $online_num
                    ];
                    if(isset($this->connections[$fd])){
                        $this->connections[$fd]->send(json_encode($send_data));
                    }else{
                        $redis->srem($room_key,$fd);
                        $fd_room_id = $redis->get('fd_'.$fd);
                        $fd_user_id = $redis->get('user_'.$fd);
                        $this->updateSecond($fd_room_id,$fd_user_id);
                    }
                }
                return;

            // 客户端发言 message: {type:say, to_client_id:xx, content:xx}
            case 'say':
                $msg_id = Db::name('live_message')->insertGetId([
                    'room_id' => $message_data['room_id'],
                    'user_id' => $message_data['user_id'],
                    'content' => nl2br(htmlspecialchars($message_data['content'])),
                    'add_time' => time()
                ]);
                $user = Db::name('users')->field('headimgurl,nick_name')->where(['user_id' => $message_data['user_id']])->find();
                $avatar = $user['headimgurl'] ? $user['headimgurl'] : '/static/public/images/headimgurl.jpg';
                $nickname = $user['nick_name'];
                //给所有用户发送消息
                $user_list = $redis->smembers($room_key);
                foreach ($user_list as $fd){
                    $send_data = [
                        'id' => $msg_id,
                        'avatar' => $avatar,
                        'nickname' => $nickname,
                        'type' => 'say',
                        'fd_id' => $fd,
                        'room_id' => $message_data['room_id'],
                        'name' => $message_data['name'],
                        'user_id' => $message_data['user_id'],
                        'content'=>nl2br(htmlspecialchars($message_data['content'])),
                        '_add_time' => date('Y-m-d H:i'),
                    ];
                    if(isset($this->connections[$fd])){
                        $this->connections[$fd]->send(json_encode($send_data));
                    }else{
                        $redis->srem($room_key,$fd);
                        $fd_room_id = $redis->get('fd_'.$fd);
                        $fd_user_id = $redis->get('user_'.$fd);
                        $this->updateSecond($fd_room_id,$fd_user_id);
                    }
                }
                return;
            case 'coupon':
                //给所有用户发送消息
                $user_list = $redis->smembers($room_key);
                foreach ($user_list as $fd){
                    $send_data = [
                        'type' => 'coupon',
                        'fd_id' => $fd,
                        'room_id' => $message_data['room_id'],
                        'name' => $message_data['name'],
                        'user_id' => $message_data['user_id'],
                        'coupon_id' => $message_data['coupon_id']
                    ];
                    if(isset($this->connections[$fd])){
                        $this->connections[$fd]->send(json_encode($send_data));
                    }else{
                        $redis->srem($room_key,$fd);
                        $fd_room_id = $redis->get('fd_'.$fd);
                        $fd_user_id = $redis->get('user_'.$fd);
                        $this->updateSecond($fd_room_id,$fd_user_id);
                    }
                }
                return;
            case 'lucky':
                //给所有用户发送消息
                $user_list = $redis->smembers($room_key);
                foreach ($user_list as $fd){
                    $send_data = [
                        'type' => 'lucky',
                        'fd_id' => $fd,
                        'room_id' => $message_data['room_id'],
                        'name' => $message_data['name'],
                        'user_id' => $message_data['user_id'],
                        'lucky_id' => $message_data['lucky_id']
                    ];
                    if(isset($this->connections[$fd])){
                        $this->connections[$fd]->send(json_encode($send_data));
                    }else{
                        $redis->srem($room_key,$fd);
                        $fd_room_id = $redis->get('fd_'.$fd);
                        $fd_user_id = $redis->get('user_'.$fd);
                        $this->updateSecond($fd_room_id,$fd_user_id);
                    }
                }
                return;
            case 'task':
                //给所有用户发送消息
                $user_list = $redis->smembers($room_key);
                foreach ($user_list as $fd){
                    $send_data = [
                        'type' => 'task',
                        'fd_id' => $fd,
                        'room_id' => $message_data['room_id'],
                        'name' => $message_data['name'],
                        'user_id' => $message_data['user_id'],
                        'task_id' => $message_data['task_id']
                    ];
                    if(isset($this->connections[$fd])){
                        $this->connections[$fd]->send(json_encode($send_data));
                    }else{
                        $redis->srem($room_key,$fd);
                        $fd_room_id = $redis->get('fd_'.$fd);
                        $fd_user_id = $redis->get('user_'.$fd);
                        $this->updateSecond($fd_room_id,$fd_user_id);
                    }
                }
                return;
            case 'goods':
                //给所有用户发送消息
                $user_list = $redis->smembers($room_key);
                foreach ($user_list as $fd){
                    $send_data = [
                        'type' => 'goods',
                        'fd_id' => $fd,
                        'room_id' => $message_data['room_id'],
                        'name' => $message_data['name'],
                        'user_id' => $message_data['user_id'],
                        'goods_id' => $message_data['goods_id']
                    ];
                    if(isset($this->connections[$fd])){
                        $this->connections[$fd]->send(json_encode($send_data));
                    }else{
                        $redis->srem($room_key,$fd);
                        $fd_room_id = $redis->get('fd_'.$fd);
                        $fd_user_id = $redis->get('user_'.$fd);
                        $this->updateSecond($fd_room_id,$fd_user_id);
                    }
                }
                return;
        }
    }
    // 定时检查连接是否有效
    public function onWorkerStart(\Workerman\Worker $worker)
    {
        $redis = new \Redis();
        $redis->connect('127.0.0.1', 6379);
        $timer = Timer::add(10, function () use (&$worker,$redis) {
            $time_now = time();
            foreach ($worker->connections as $connection) {
                if (empty($connection->lastMessageTime)) {
                    $connection->lastMessageTime = $time_now;
                    continue;
                }
                if ($time_now - $connection->lastMessageTime > 12) {
                    $client_id = $connection->id;
                    $user_id = $redis->get('user_'.$client_id);
                    if(isset($this->connections[$client_id])){
                        $room_id = $redis->get('fd_'.$client_id);
                        $room_key = 'live_'.$room_id;
                        $redis->srem($room_key,$client_id);
                        $this->connections[$client_id]->close();
                        $fd_user_id = $redis->get('user_'.$client_id);
                        $this->updateSecond($room_id,$fd_user_id);
                    }
                }
            }
        });
    }
    /**
     * 当客户端断开连接时
     * @param integer $client_id 客户端id
     */
    public function onClose($connection)
    {
        $client_id = $connection->id;
        $redis = new \Redis();
        $redis->connect('127.0.0.1', 6379);
        $room_id = $redis->get('fd_'.$client_id);
        $user_id = $redis->get('user_'.$client_id);
        $room_key = 'live_'.$room_id;
        $redis->srem($room_key,$client_id);
        $userInfo = $redis->get('live_'.$room_id.'_'.$user_id);
        if(isset($this->connections[$client_id])){
            unset($this->connections[$client_id]);
        }
        $this->updateSecond($room_id,$user_id);
        if($userInfo){
            $userInfo = json_decode($userInfo,true);
            $user_list = $redis->smembers($room_key);
            foreach ($user_list as $fd){
                $send_data = [
                    'type' => 'logout',
                    'fd_id' => $fd,
                    'room_id' => $userInfo['room_id'],
                    'name' => $userInfo['name'],
                    'user_id' => $userInfo['user_id'],
                ];
                if(isset($this->connections[$fd])) {
                    $this->connections[$fd]->send(json_encode($send_data));
                }else{
                    $redis->srem($room_key,$fd);
                    $fd_room_id = $redis->get('fd_'.$fd);
                    $fd_user_id = $redis->get('user_'.$fd);
                    $this->updateSecond($fd_room_id,$fd_user_id);
                }
            }
        }

        return;
    }

    public function updateSecond($room_id,$user_id)
    {
        $liveUser = Db::name('live_user')->where(['live_id' => $room_id,'user_id' => $user_id])->find();
        if($liveUser && $liveUser['upd_time'] > 0){
            Db::name('live_user')->where(['live_id' => $room_id,'user_id' => $user_id])->update([
                'second' => $liveUser['second'] + (time() - $liveUser['upd_time']),
                'upd_time' => time(),
                'is_online' => 0
            ]);
            //扣除总时长
            $liveInfo = Db::name('live')->where(['id' => $room_id])->find();
//            $saas_account = Db::name('saas_account')->where('id',$liveInfo['saas_id'])->find();
//            if($saas_account){
//                $use_flow = (time() - $liveUser['upd_time']) * config('config.live_second_data');
//                Db::name('saas_account')->where(['id' => $liveInfo['saas_id']])->update([
//                    'live_time' => $saas_account['live_time'] - $use_flow
//                ]);
//                Db::name('live')->where(['id' => $room_id])->inc('use_resource',$use_flow)->update();
//            }
        }else{
            Db::name('live_user')->where(['live_id' => $room_id,'user_id' => $user_id])->update([
                'is_online' => 0
            ]);
        }
    }
}
